package org.shiro.auth.controller;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;

@Controller
public class LoginController {

  @Autowired
  DefaultWebSessionManager      defaultWebSessionManager;

  private final String          IS_CONSUMED_KEY = "IS_CONSUMED";

  static Map<String, UserLogin> users           = new HashMap<>();

  static {
    UserLogin zhang3 = new UserLogin("zhang3", "111111");
    UserLogin li4 = new UserLogin("li4", "111111");
    users.put("zhang3", zhang3);
    users.put("li4", li4);
  }

  @PostMapping("login")
  @ResponseBody
  public R login(String username, String password, String service) {
    UserLogin user = users.get(username);
    if (user == null) {
      return R.error("用户名、密码错误");
    }
    if (username.equals(users.get(username).getUsername()) && password.equals(users.get(username).getPassword())) {
      Subject subject = SecurityUtils.getSubject();
      UsernamePasswordToken token = new UsernamePasswordToken(username, password);
      subject.login(token);
      String accessToken = (String) subject.getSession().getId();
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("service", service + "?accessToken=" + accessToken);
      return R.ok(map);
    }
    return R.error("用户名、密码错误");
  }

  @GetMapping("login")
  public String login(HttpServletRequest request, HttpServletResponse response, String service, Model model) {
    Cookie cookie = getCookie(request);
    if (cookie != null) {
      String jsessionId = cookie.getValue();
      try {
        Session session = defaultWebSessionManager.getSessionDAO().readSession(jsessionId);
        if (session != null) {
          return "redirect:" + service + "?accessToken=" + jsessionId;
        }
      } catch (Exception e) {// 发生异常，cookie值无效
      }
    }
    model.addAttribute("service", service);
    return "login";
  }

  private Cookie getCookie(HttpServletRequest request) {
    javax.servlet.http.Cookie cookies[] = request.getCookies();
    if (cookies != null) {
      for (javax.servlet.http.Cookie cookie : cookies) {
        if (cookie.getName().equals("JSESSIONID")) {
          return cookie;
        }
      }
    }
    return null;
  }

  /**
   * 验证accessToken是否有效
   * 
   * @author zhangz8@yeah.net
   * @date 2020年8月28日下午1:39:46
   * @param accessToken
   * @return
   */
  @GetMapping("isValid")
  @ResponseBody
  public RpcResponse isValid(String accessToken) {
    Session session = null;
    try {
      session = defaultWebSessionManager.getSessionDAO().readSession(accessToken);
    } catch (Exception e) {
    }
    if (session == null) {
      return RpcResponse.success(Boolean.FALSE);
    }

    return RpcResponse.success(Boolean.TRUE);
  }

  /**
   * 验证accessToken是否消费了
   * 
   * @author zhangz8@yeah.net
   * @date 2020年8月28日下午1:39:11
   * @param accessToken
   * @return
   */
  @GetMapping("isConsumed")
  @ResponseBody
  public RpcResponse isConsumed(String accessToken) {
    Session session = null;
    try {
      session = defaultWebSessionManager.getSessionDAO().readSession(accessToken);
    } catch (Exception e) {
    }
    if (session != null) {
      String isConsumed = (String) session.getAttribute(IS_CONSUMED_KEY);
      if (StringUtils.isBlank(isConsumed) || "false".equalsIgnoreCase(isConsumed)) {
        session.setAttribute(IS_CONSUMED_KEY, "TRUE");
        return RpcResponse.success(Boolean.FALSE);
      }
      if ("true".equalsIgnoreCase(isConsumed)) {
        return RpcResponse.success(Boolean.TRUE);
      }
    }
    return RpcResponse.success(Boolean.TRUE);
  }

}
